
/*
 * Copyright (c) 2010 Sergey N Frolov
 * 
 * See LICENSE file
 */

#ifndef _NGX_HTTP_JAVASCRIPT_MODULE_H_INCLUDED_
#define _NGX_HTTP_JAVASCRIPT_MODULE_H_INCLUDED_

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <nginx.h>

#define XP_UNIX
#include <jsapi.h>
#include <jsdate.h>
#include <jsxdrapi.h>
#include <jsdbgapi.h>

typedef struct {
	JSRuntime *jsr;
	size_t memory;
} ngx_http_javascript_main_conf_t;

typedef struct {
	size_t quota;
	ngx_str_t magic;
	ngx_str_t output;
	ngx_str_t basedir;
	ngx_str_t realdir;
	ngx_int_t timeout;
	ngx_flag_t enable;
	ngx_flag_t cache_xdr;
	size_t max_post;
	size_t max_data;
} ngx_http_javascript_loc_conf_t;

typedef struct {
	ngx_http_request_t *r;
	ngx_int_t timeout;
	ngx_str_t path;
	size_t root;
} ngx_javascript_private_t;

typedef struct ngx_javascript_multi_part_s {
	ngx_http_request_t *r;// Request
	ngx_file_t *file;     // File descriptor and more
	size_t length;        // Length of whole file
	size_t offset;        // Current read offset
	ngx_str_t boundary;   // Boundary as string
	u_char *b;            // Read buffer
	size_t l;             // Buffer length
	size_t o;             // Buffer offset in file
	u_char *h;            // Current header
	size_t hl;            // Current header length
	size_t ho;            // Current header offset
	size_t rn;            // end-of-line length (1 when \n, 2 when \r\n)
} ngx_javascript_multi_part_t;

extern ngx_module_t ngx_http_javascript_module;

void *ngx_http_javascript_create_main_conf(ngx_conf_t *cf);
char *ngx_http_javascript_init_main_conf(ngx_conf_t *cf, void *conf);
void *ngx_http_javascript_create_loc_conf(ngx_conf_t *cf);
char *ngx_http_javascript_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
char *ngx_http_javascript_init_post(ngx_conf_t *cf, void *cmd, void *conf);

ngx_int_t ngx_http_javascript_handler(ngx_http_request_t *r);
ngx_int_t ngx_http_javascript_handle_request(ngx_http_request_t *r);
void ngx_http_javascript_handle_request_data(ngx_http_request_t *r);

JSBool ngx_javascript_error(JSContext *jcx, const char *message);

void ngx_javascript_global_error(JSContext *jcx, const char *message, JSErrorReport *report);
void ngx_javascript_log(JSContext *jcx, const char *message);
JSBool ngx_javascript_outofmemory(JSContext *jcx);
JSBool ngx_javascript_timeout(JSContext *jcx);

JSBool ngx_javascript_global_load(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_global_alert(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_global_print(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_global_sleep(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_global_usleep(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_file_string(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JSBool ngx_javascript_line_string(JSContext *jcx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);

JSBool ngx_javascript_read_server(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);
JSBool ngx_javascript_read_headers(JSContext *jcx, JSObject *obj, JSObject *global_server, ngx_http_request_t *r);
JSBool ngx_javascript_read_request(JSContext *jcx, JSObject *obj, ngx_http_request_t *r, int arg);
JSBool ngx_javascript_write_headers(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);
JSBool ngx_javascript_read_application_x_www_form_urlencoded(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);

JSBool ngx_javascript_read_multipart_form_data(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);
JSBool ngx_javascript_read_multipart_form_data_file(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);

ngx_str_t ngx_javascript_request_body(ngx_http_request_t *r);
u_char *ngx_javascript_read_line(u_char *s, u_char *e);
size_t ngx_javascript_read_data_file(ngx_javascript_multi_part_t *m, size_t s);
JSBool ngx_javascript_get_boundary(ngx_http_request_t *r, u_char **boundary_data, size_t *boundary_length);
JSBool ngx_javascript_multipart_headers(ngx_javascript_multi_part_t *m, u_char **rvar, size_t *rvar_len, u_char **rname, size_t *rname_len);
JSBool ngx_javascript_read_line_file(ngx_javascript_multi_part_t *m, size_t s, size_t *ro, u_char **rp);
JSBool ngx_javascript_read_boundary(ngx_javascript_multi_part_t *m, u_char *s, u_char **rp);
JSBool ngx_javascript_read_boundary_file(ngx_javascript_multi_part_t *m, size_t s, size_t *ro, u_char **rp);
JSBool ngx_javascript_read_multipart_form_data(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);
JSBool ngx_javascript_read_multipart_form_data_file(JSContext *jcx, JSObject *obj, ngx_http_request_t *r);

JSBool ngx_javascript_register_variable(JSContext *jcx, JSObject *obj, ngx_http_request_t *r, u_char *var, size_t var_len, u_char *val, size_t val_len);
JSBool ngx_javascript_register_variable_r(JSContext *jcx, JSObject *obj, ngx_http_request_t *r, u_char *var, size_t var_len, u_char *val, size_t val_len);

JSBool ngx_javascript_fullpath(JSContext *jcx, char *filename, char *fullname);
JSBool ngx_javascript_check_basedir(JSContext *jcx, char *filename, int mode);
JSBool ngx_javascript_check_basedir_realpath(JSContext *jcx, const char *filename);
JSBool ngx_javascript_execute_script(JSContext *jcx, JSObject *obj, const char *fileName, jsval *rval);

JSBool ngx_javascript_file_line(JSContext *jcx, const char **file, int *line);

u_char *ngx_javascript_string_token(u_char *s, const u_char *delim, u_char ** last);
u_char *ngx_pstrdup0(ngx_pool_t *pool, ngx_str_t *src);

#define NGX_JAVASCRIPT_PRIVATE_ERROR "Fatal server error"
#define NGX_JAVASCRIPT_ENOENT_ERROR "No such file or directory"

#define NGX_JAVASCRIPT_BUFFER 4096
#define NGX_JAVASCRIPT_BUFFER1 1024
#define NGX_JAVASCRIPT_BUFFER2 8192

#define NGX_JAVASCRIPT_PARSE_POST 0
#define NGX_JAVASCRIPT_PARSE_GET 1
#define NGX_JAVASCRIPT_PARSE_COOKIE 2
#define NGX_JAVASCRIPT_PARSE_STRING 3
#define NGX_JAVASCRIPT_PARSE_ENV 4
#define NGX_JAVASCRIPT_PARSE_SERVER 5
#define NGX_JAVASCRIPT_PARSE_SESSION 6

#ifdef NGX_JAVASCRIPT_HAVE_FILE
extern JSBool ngx_javascript_init_file(JSContext *jcx, JSObject *global);
#endif /* NGX_JAVASCRIPT_HAVE_FILE */

#ifdef NGX_JAVASCRIPT_HAVE_MYSQL
extern JSBool ngx_javascript_init_mysql(JSContext *jcx, JSObject *global);
#endif /* NGX_JAVASCRIPT_HAVE_MYSQL */

#ifdef NGX_JAVASCRIPT_HAVE_SQLITE
extern JSBool ngx_javascript_init_sqlite(JSContext *jcx, JSObject *global);
#endif /* NGX_JAVASCRIPT_HAVE_SQLITE */

#endif /* _NGX_HTTP_JAVASCRIPT_MODULE_H_INCLUDED_ */
